package com.vains.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.vains.dto.AuthorityDto;
import com.vains.entity.OauthPermission;
import com.vains.entity.OauthRolePermission;
import com.vains.entity.OauthUser;
import com.vains.entity.OauthUserRole;
import com.vains.service.IOauthPermissionService;
import com.vains.service.IOauthRolePermissionService;
import com.vains.service.IOauthUserRoleService;
import com.vains.service.IOauthUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * security 自带的userDetailService的实现
 *
 * @author vains
 * @version 1.0
 * @since 2020/6/8 1:13
 **/
@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    private final IOauthUserService oauthUserService;

    private final IOauthUserRoleService oauthUserRoleService;

    private final IOauthPermissionService oauthPermissionService;

    private final IOauthRolePermissionService oauthRolePermissionService;

    @Autowired
    public UserDetailsServiceImpl(IOauthUserService oauthUserService, IOauthUserRoleService oauthUserRoleService, IOauthRolePermissionService oauthRolePermissionService, IOauthPermissionService oauthPermissionService) {
        this.oauthUserService = oauthUserService;
        this.oauthUserRoleService = oauthUserRoleService;
        this.oauthRolePermissionService = oauthRolePermissionService;
        this.oauthPermissionService = oauthPermissionService;
    }

    @Override
    public UserDetails loadUserByUsername(String phoneOrNumber) {
        QueryWrapper<OauthUser> wrapper = new QueryWrapper<>();
        wrapper.eq("user_phone", phoneOrNumber);
        wrapper.or();
        wrapper.eq("user_number", phoneOrNumber);
        wrapper.or();
        wrapper.eq("user_name", phoneOrNumber);
        OauthUser oauthUser = oauthUserService.getOne(wrapper);
        Assert.notNull(oauthUser, "用户不存在！");
        // 权限列表
        Set<AuthorityDto> grantedAuthorities = new HashSet<>();
        QueryWrapper<OauthUserRole> userRoleWrapper = new QueryWrapper<>();
        userRoleWrapper.eq("user_id", oauthUser.getUserId());
        // 查询用户对应的角色
        List<OauthUserRole> roles = oauthUserRoleService.list(userRoleWrapper);
        if (CollectionUtils.isEmpty(roles)) {
            oauthUser.setAuthorities(grantedAuthorities);
            return oauthUser;
        }
        // Assert.notEmpty(roles, "用户没有任何角色！");
        // 获取角色对应ID
        List<Integer> roleIds = roles.stream().map(OauthUserRole::getRoleId).collect(Collectors.toList());
        QueryWrapper<OauthRolePermission> rolePermissionWrapper = new QueryWrapper<>();
        rolePermissionWrapper.in("role_id", roleIds);
        // 根据角色ID查询角色对应权限
        List<OauthRolePermission> rolePermissions = oauthRolePermissionService.list(rolePermissionWrapper);
        // Assert.notEmpty(rolePermissions, "用户没有任何权限！");
        if (CollectionUtils.isEmpty(rolePermissions)) {
            oauthUser.setAuthorities(grantedAuthorities);
            return oauthUser;
        }
        // 获取权限ID
        List<Integer> permissionIds = rolePermissions.stream().map(OauthRolePermission::getPermissionId).collect(Collectors.toList());
        QueryWrapper<OauthPermission> permissionWrapper = new QueryWrapper<>();

        permissionWrapper.in("permission_id", permissionIds);
        // 根据权限ID获取用户对应权限
        List<OauthPermission> permissions = oauthPermissionService.list(permissionWrapper);
        if (CollectionUtils.isEmpty(permissions)) {
            oauthUser.setAuthorities(grantedAuthorities);
            return oauthUser;
        }
        // Assert.notEmpty(rolePermissions, "用户没有任何权限！");
        for (OauthPermission permission : permissions) {
            if (!StringUtils.isEmpty(permission.getPermissionUrl())) {
                // 将权限存入指定权限集合
                AuthorityDto authority = new AuthorityDto();
                authority.setAuthority(permission.getPermissionUrl());
                grantedAuthorities.add(authority);
            }
        }
        // 放入 security 内置User对象中
        oauthUser.setAuthorities(grantedAuthorities);
        return oauthUser;
    }
}
